package com.benmei.ntlive.utils;

import com.benmei.ntlive.constant.ConnectType;
import com.benmei.ntlive.server.netty.SessionRepository;
import com.benmei.ntlive.server.netty.websocket.WebSocketServerHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.ScheduledFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Create by chenhong on 2018/10/27 13:34
 * Description : netty channel 方法工具，根据不同的连接调用不同的方法
 */
public  class ChannelUtil {
    private static Logger logger = LoggerFactory.getLogger(ChannelUtil.class);

    public static void exitChannelByException(ChannelHandlerContext ctx, Throwable cause, SessionRepository sessionRepository) throws Exception{


        logger.error(cause.getMessage(), cause);
        // 从教室里面移除一个人，如果这时教室已空就移除教室。
        String channelKey = ctx.channel().remoteAddress().toString();
        logger.debug("Current room size is {}", sessionRepository.size());
        /**
         * resive by C.H on 2018/10/29 13:22
         * 修改：heartBeat从sessionRepository的TaskMap中获取
         */
        ScheduledFuture<?> heartBeat = sessionRepository.getTaskMap().get(channelKey);
        if (heartBeat != null) {
            logger.info(" \n       / cancel schedule task ------》》》》》》》》" + heartBeat.toString());
            boolean cancelSuccess = heartBeat.cancel(true);
            logger.info("channelInactive: 关闭心跳 for client:" + channelKey + " cancelHeartBeatSuccess:" + cancelSuccess + "heartBeatInstance" + heartBeat.toString());
            heartBeat = null;
        }
        sessionRepository.remove(channelKey);
        /**
         * resive by C.H on 2018/10/29 19:37
         * 修改：移除心跳任务
         */
        sessionRepository.getTaskMap().remove(channelKey);

        logger.info("exceptionCaught: 移除客户端[{}]后Current room size is {}", channelKey, sessionRepository.size());
        // 释放资源
        ctx.close();
        logger.info("exceptionCaught：释放资源 for client:{}", channelKey);
        ctx.fireExceptionCaught(cause);
    }

    public static  ChannelType get(int connectType){
        // 返回类型socket的工具
        if(connectType== ConnectType.SOCKET)
            return new ScoketChannel();
        else{
            // 返回类型websocket的工具
            return  new WebSocketChannel();
        }
    }


    //channel或者ChannelHandlerContext中的方法
    public interface ChannelType{
        ChannelFuture writeAndFlush(Channel channel, Object o);
        ChannelFuture writeAndFlush(ChannelHandlerContext ctx, Object o);
    }

    //socket的方法实现
    public static class ScoketChannel implements ChannelType{
        @Override
        public ChannelFuture writeAndFlush(Channel channel, Object o) {
            return channel.writeAndFlush(o);
        }
        @Override
        public ChannelFuture writeAndFlush(ChannelHandlerContext ctx, Object o) {
            return ctx.writeAndFlush(o);
        }
    }
    //websocket的方法实现
    public static class WebSocketChannel implements ChannelType{

        @Override
        public ChannelFuture writeAndFlush(Channel channel, Object o) {
            String str= (String) o;
            return channel.writeAndFlush(new TextWebSocketFrame(str));
        }

        @Override
        public ChannelFuture writeAndFlush(ChannelHandlerContext ctx, Object o) {
            String str= (String) o;
            return ctx.writeAndFlush(new TextWebSocketFrame(str));
        }
    }
}
